/*
 * REFTimerService.h
 *
 *  Created on: Jun 12, 2013
 *      Author: Lucifer
 */

#ifndef REFTIMERSERVICE_H_
#define REFTIMERSERVICE_H_

#include "REFServiceRegistry.h"

namespace BFX
{

class REFEventReactor;

/**
 *
 */
class REFEventContext : public REFObject
{
public:
	REFEventContext()
	{
	}

	void Invoke();
};

/**
 *
 */
class REFTimerContext : public REFEventContext
{
public:
	REFTimerContext(REFTimer* pTimer, TimerCallback callback);

	REFTimer* GetTimer() const;

private:
	REF<REFTimer>	m_pTimer;
	TimerCallback	m_callback;
};

/**
 * Represents a reference based list of event contexts.
 */
typedef	REFWrapper<List<REF<REFEventContext> > > REFEventContextList;

/**
 *
 */
class REFTimerQueue : public REFObject
{
public:
	/**
	 * Initializes a new instance of the BFX::REFTimerQueue.
	 */
	REFTimerQueue();

	/**
	 * Determine whether there are no timers in the queue.
	 * @return True if the queue is empty; otherwise false.
	 */
	bool IsEmpty() const;

	/**
	 * Enqueue a new timer to the queue.
	 * @param pContext
	 * @return True if the timer is earliest in the queue, in which case the reactor's event demultiplexing function
	 * 		call may need to be interrupted and restarted; otherwise false.
	 */
	bool EnqueueContext(REFTimerContext* pContext);

	/**
	 * Dequeue all timer contexts.
	 * @param pContexts
	 */
	void DequeueAllContexts(REFEventContextList* pContexts);
	/**
	 * Dequeue all ready timer contexts.
	 * @param pContexts
	 */
	void DequeueReadyContexts(REFEventContextList* pContexts);

private:
	// Move the item at the given index up the array to its correct position.
	void MoveUpTimers(int nIndex);

	// Move the itme at the given index down the array to its currect position.
	void MoveDownTimers(int nIndex);

private:
	struct TimerPair
	{
		Time m_time;				// The time when the timer should fire.
		REFTimer* m_pTimer;			// The associated timer with enqueued contexts.
	};

	REFTimer*	m_pTimers;			// The head of linked timers.
	Array<REFTimer*>	m_sortQueue;

	REF<REFTimerQueue>	m_pNext;
};

/**
 * Provides services of timer operations based on event dispatcher.
 */
class REFTimerService : public REFServiceBase<REFTimerService>
{
public:
	/**
	 * Initializes a new instance of BFX::REFTimerService.
	 * @param pDispatcher The own event dispatcher.
	 */
	REFTimerService(REFEventDispatcher* pDispatcher);
	/**
	 * Destroys the BFX::REFTimerService instance.
	 */
	virtual ~REFTimerService();

	/**
	 * Shutdown this service.
	 */
	virtual void Shutdown();

	/**
	 * Cancel any asynchronous wait operations associated with the timer.
	 * @param pTimer
	 * @return Number of operations were canceled.
	 */
	int Cancel(REFTimer* pTimer);

	/**
	 * Perform a blocking wait on the timer.
	 * @param pTimer
	 */
	void Wait(REFTimer* pTimer);
	/**
	 * Starts an asynchronous wait on the timer.
	 * @param pTimer
	 * @param callback
	 */
	void WaitAsync(REFTimer* pTimer, TimerCallback callback);

private:
	REF<REFEventReactor>	m_pReactor;
	REF<REFTimerQueue>	m_pTimerQueue;
};

} /* namespace BFX */
#endif /* REFTIMERSERVICE_H_ */
